<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BRepository2
 *
 * @author ID59C
 */
class BRepository2 {

    public function getCount($entity, $context = NULL) {
        //$context = self::getContext($context, $entity);
        $mClass = $entity->getModelClass();
        $count = $mClass::model()->count();
        return $count;
    }

    /**
     * 
     * @param BEntity $entity, use to store condition for find entity
     */
    public function findAllEntities($entity) {
        $entities = array();
        if ($entity instanceof BEntity) {
            /*
              if ($entity->getId() != NULL) {
              //$entity->load();
              $entities[$entity->getId()] = $entity;
              return $entities;
              }
             * 
             */
            $mClass = $entity->getModelClass();
            $findContext = $entity->getFindContext();
            $findCondition = $findContext['condition'];
            $findParams = $findContext['params'];

            $mObjs = $mClass::model()->findAll($findCondition, $findParams);
            $class = get_class($entity);
            foreach ($mObjs as $mObj) {
                /* if (isset($mObj->classname) && $mObj->classname != NULL)
                  $class = $mObj->classname;
                 * 
                 */
                if ($mObj != NULL) {
                    if (isset($mObj->classname) && $mObj->classname != NULL)
                        $class = $mObj->classname;
                    if ($class != get_class($entity)) {
                        if ($entity instanceof BApp)
                            $entity2 = new $class(BApp::Not_Load_By_ClassName);
                        else
                            $entity2 = new $class();
                    } else
                        $entity2 = clone $entity;

                    $loadList = $entity2->getLoadList();
                    $loadItems = array();

                    if ($loadList != NULL) {
                        foreach ($loadList as $property => $colName) {
                            if (isset($mObj->$colName))
                                $loadItems[$property] = $mObj->$colName;
                        }
                        $entity2->loadData($loadItems);
                    }

                    $attributes = $mObj->getAttributes();
                    if (isset($attributes['_id'])) {
                        $entity2->id = $mObj->_id;
                        $entities[$mObj->_id] = $entity2;
                    } else if (isset($attributes['id'])) {
                        $entity2->id = $mObj->id;
                        $entities[$mObj->id] = $entity2;
                    }
                }
            }

            return $entities;
        }
    }

    /**
     * 
     * @param BEntity $entity
     */
    public function saveEntity(&$entity) {

        $mClass = $entity->getModelClass();

        //save exist item
        if ($entity->getId() != NULL) {
            $mObj = $mClass::model()->findByPk($entity->getId());
        } else {//add new row
            $mObj = new $mClass();
        }

        $saveItems = $entity->getSaveItems();

        $tempItems = array();

        foreach ($saveItems as $col => $value) {
            $tempItems[$col] = $value;
            $mObj->$col = $value;
        }

        try {
            $mObj->save();
        } catch (Exception $e) {
            echo 'Caught exception: ', $e->getMessage(), "\n";
        }

        $attributes = $mObj->getAttributes();

        if (isset($attributes['_id']))
            $entity->id = $mObj->_id;
        if (isset($attributes['id']))
            $entity->id = $mObj->id;

        return $entity->id;
    }

    public function loadEntity(&$entity) {

        $reload = FALSE;
        $class = get_class($entity);

        //only load when id exist in entity
        if ($entity->id != NULL)
            $reload = TRUE;

        if ($reload === TRUE) {
            //$context = new BDataObjContext(get_class($entity), $data);
            $mClass = $entity->getModelClass();
            //$entity->id = $context->id;
            $mObj = $mClass::model()->findByPk($entity->id);

            if ($mObj != NULL) {
                if (isset($mObj->classname)) {
                    $class = $mObj->classname;
                    if ($class != get_class($entity)) {
                        if ($entity instanceof BApp)
                            $entity = new $class(BApp::Not_Load_By_ClassName);
                        else
                            $entity = new $class();
                    }
                }

                $loadList = $entity->getLoadList();
                $loadItems = array();

                if ($loadList != NULL) {
                    foreach ($loadList as $property => $colName) {
                        if (property_exists(get_class($entity), $property))
                            if (isset($mObj->$colName))
                                $loadItems[$property] = $mObj->$colName;
                    }
                    $entity->loadData($loadItems);
                }
                //return new $class($mObj->_id);
            }
        }

        return $reload;
    }

    /**
     * 
     * @param BEntity $entity
     * @return boolean
     */
    public function deletEntity($entity) {

        //$context = self::getContext($context, $entityClass);

        $mClass = $entity->getModelClass();

        $id = $entity->getId();

        $status = BStatus::find(BStatus::Status_Object_Deleted)->getId();

        //delete just change status
        if ($id != NULL) {
            $mObj = $mClass::model()->findByPk($id);
            $mObj->status = $status;
            $result = $mObj->save();
            return $result;
        }

        return FALSE;
    }

    /**
     * 
     * @param BEntity $entity
     * @param BEntity $parent
     * @return type
     */
    public function addChildItem($entity, $parent) {

        $mChildClass = $entity->getModelClass() . 'Child';
        $spaceId = isset($parent->spaceId) ? $parent->spaceId : NULL;
        $appId = isset($parent->appId) ? $parent->appId : NULL;
        $parentId = $parent->getId();
        $childId = $entity->getId();

        if (!self::isSingleTreeItem($entity)) {
            $mRow = new $mChildClass();
            $mRow->parent_id = $parentId;
            $mRow->child_id = $childId;
            if ($spaceId != NULL)
                $mRow->space_id = $spaceId;
            if ($appId != NULL)
                $mRow->app_id = $appId;
            return $mRow->save();
        }
        else {
            if ($entity instanceof BEntity) {
                $entity->parentId = $parentId;
                return $this->saveEntity($entity);
            }
        }
        //return TRUE;
    }

    /**
     * 
     * @param BEntity $entity
     * @param BEntity $parent
     * @return boolean
     */
    public function removeChildItem($entity, $parent) {

        if ($entity->getId() == NULL) {
            $class = get_class($entity);
            $entity = $class::find($entity);
        }

        if ($parent->getId() == NULL) {
            $class = get_class($parent);
            $parent = $class::find($parent);
        }

        if ($entity->getId() != NULL && $parent->getId() != NULL) {
            $mClass = $entity->getModelClass();
            $mChildClass = $mClass . 'Child';
            //also delete from child table
            if (!self::isSingleTreeItem($entity)) {
                $mItemChild = $mChildClass::model()->findByAttributes(array('child_id' => $entity->getId(), 'parent_id' => $parent->getId()));
                $mItemChild->status = BStatus::Status_Object_Deleted;
                $mItemChild->save();
                //delete item form entity table
                $mItem = $mClass::model()->findByPk($itemId);
                $mItem->status = BStatus::Status_Object_Deleted;
                $mItem->save();
                return TRUE;
            } else {
                if ($entity instanceof BEntity && $parent instanceof BEntity) {
                    $entity->parentId = $parentId;
                    return $this->deletEntity($entity);
                }
            }
        }
        return FALSE;
    }

    /**
     * 
     * @param BEntity $entity
     * @return \class
     */
    public function getChildren($entity, $childContext = NULL) {

        $mClass = $entity->getModelClass();
        //$childClass = $class."Child";
        $mChildClass = $mClass . 'Child';
        $spaceId = isset($entity->spaceId) ? $entity->spaceId : NULL;
        $appId = isset($entity->appId) ? $entity->appId : NULL;

        $statusId = BStatus::Status_Deleted_Id;

        $condition = 'parent_id = :parentId and status <> :statusId';
        $params = array(':parentId' => $entity->getId(), ':statusId' => $statusId);

        $children = array();

        if (self::isSingleTreeItem($entity)) {
            $mChildClass = $mClass;
            /*
              if (!strcmp($mClass, "BMAttribute")) {
              $condition = 'status <> :statusId';
              $params = array(':statusId' => $statusId);
              }
             * 
             */
        }

        if ($spaceId != NULL && $spaceId != 0) {
            $condition .= " and space_id = :spaceId";
            $params[':spaceId'] = $spaceId;
        }

        if ($appId != NULL && $appId != 0) {
            $condition .= " and app_id = :appId";
            $params[':appId'] = $appId;
        }

        //$mRows = $mChildClass::model()->findAllByAttributes(array('parent_id' => $this->getId(), 'status' => $statusId));
        $mRows = $mChildClass::model()->findAll(array('condition' => $condition, 'params' => $params));

        if (is_array($childContext) && $childContext != NULL) {
            if (isset($childContext['spaceId']))
                $spaceId = $childContext['spaceId'];
            if (isset($childContext['appId']))
                $appId = $childContext['appId'];
        }

        if ($childContext instanceof BEntity) {
            $spaceId = property_exists(get_class($childContext), 'spaceId') ? $childContext->spaceId : NULL;
            $appId = property_exists(get_class($childContext), 'appId') ? $childContext->appId : NULL;
        }


        $class = get_class($entity);
        foreach ($mRows as $mRow) {
            $isSelected = TRUE;
            $itemId = $mRow->hasAttribute('child_id') ? $mRow->child_id : $mRow->getPrimaryKey();
            /*
              $child = new $class($itemId);
              if ($spaceId != NULL) {
              if ($child->spaceId != $spaceId) {
              $isSelected = FALSE;
              }
              }
              if ($appId != NULL) {
              if ($child->appId != $appId)
              $isSelected = FALSE;
              }
             * 
             */

            if ($isSelected)
                $children[$itemId] = $item = new $class($itemId);
        }
        //return $children;
        //filter children according to childContext
        if ($childContext != NULL) {
            foreach ($children as $id => $child) {
                if (is_array($childContext)) {
                    foreach ($childContext as $property => $value)
                        if (isset($child->$property) && $value != NULL && $value != 0 && $child->$property != $value)
                            unset($children[$id]);
                }
                if ($childContext instanceof $class) {
                    $properties = get_object_vars($childContext);
                    foreach ($properties as $property => $value) {
                        if ($value != null && $value != BEntity::String_Any && $value != 0 && $child->$property != NULL && $child->$property != BEntity::String_Any && $child->$property != $value)
                            unset($children[$id]);
                    }
                }
                if (is_string($childContext))
                    if ($child->name != $childContext)
                        unset($children[$id]);
            }
        }

        return $children;
    }

    /**
     * 
     * @param BEntity $entity
     * @return \class
     */
    public function getParent($entity) {

        $mClass = $entity->getModelClass();
        //$childClass = $class."Child";
        $mChildClass = $mClass . 'Child';

        $statusId = BStatus::Status_Deleted_Id;

        $condition = 'child_id= :childId and status != :statusId';
        $params = array(':childId' => $entity->getId(), ':statusId' => $statusId);

        if (self::isSingleTreeItem($entity)) {
            $mChildClass = $mClass;
            $condition = '_id= :childId and status != :statusId';
            $params = array(':childId' => $entity->getId(), ':statusId' => $statusId);
        }

        //$mRows = $mChildClass::model()->findAllByAttributes(array('parent_id' => $this->getId(), 'status' => $statusId));
        $mRows = $mChildClass::model()->findAll(array('condition' => $condition, 'params' => $params));

        $parents = array();
        $class = get_class($entity);

        foreach ($mRows as $mRow) {
            $itemId = $mRow->parent_id;
            $parents[$itemId] = $item = new $class($itemId);
        }

        return $parents;
    }

    /**
     * 
     * @param BEntity $group
     * @param BEntity $member
     * @param type $context
     * @return boolean
     */
    public function addGroupMember($group, $member) {

        //$context = self::getContext($context);
        //$mClass = $context->getModelClass(get_class($group)) . 'Member';
        $groupClass = get_class($group);

        if ($member != NULL) {
            $memberClass = get_class($member);
            $tempClass = str_replace("Group", '', $groupClass);
            $memberId = $member->getId();
            $statusId = BStatus::Status_Deleted_Id;
            if ($tempClass == $memberClass || $member instanceof $tempClass) {
                $mClass = $group->getModelClass() . 'Member';

                $condition = 'group_id = :GroupId
					and member_id = :MemberId and status <> :StatusId';
                $params = array(':StatusId' => $statusId,
                    ':GroupId' => $group->getId(), ':MemberId' => $memberId);

                if ($mClass::model()->hasAttribute('group_class')) {
                    $condition.=' and group_class=:GroupClass';
                    $params[':GroupClass'] = $groupClass;
                }

                if ($mClass::model()->hasAttribute('member_class')) {
                    $condition.=' and member_class=:MemberClass';
                    $params[':MemberClass'] = $memberClass;
                }

                if ($mClass::model()->hasAttribute('space_id')) {
                    if (isset($group->spaceId) && $group->spaceId != NULL) {
                        $condition.=' and space_id=:spaceId';
                        $params[':spaceId'] = $group->spaceId;
                    }
                }

                if ($mClass::model()->hasAttribute('app_id')) {
                    if (isset($group->appId) && $group->appId != NULL) {
                        $condition.=' and app_id=:appId';
                        $params[':appId'] = $group->appId;
                    }
                }

                $mObj = $mClass::model()->find($condition, $params);

                if ($mObj == NULL) {
                    $mGroupMember = new $mClass();
                    $mGroupMember->member_id = $memberId;
                    if ($mClass::model()->hasAttribute('member_class')) {
                        $mGroupMember->member_class = $memberClass;
                    }

                    $mGroupMember->group_id = $group->getId();

                    if ($mClass::model()->hasAttribute('group_class')) {
                        $mGroupMember->group_class = $groupClass;
                    }

                    if ($mClass::model()->hasAttribute('space_id')) {
                        if (isset($group->spaceId) && is_numeric($group->spaceId)) {
                            $mGroupMember->space_id = $group->spaceId;
                        }
                    }

                    if ($mClass::model()->hasAttribute('app_id')) {
                        if (isset($group->appId) && is_numeric($group->appId)) {
                            $mGroupMember->app_id = $group->appId;
                        }
                    }

                    return $mGroupMember->save();
                }
            } else {
                $mClass = $group->getModelClass() . substr($memberClass, 1);
                $memberCol = strtolower(substr($memberClass, 1) . "_id");
                $groupCol = strtolower(substr($groupClass, 1) . "_id");

                $condition = $groupCol . ' = :GroupId and ' . $memberCol . ' = :MemberId and status != :StatusId';
                $params = array(':StatusId' => $statusId, ':GroupId' => $group->getId(), ':MemberId' => $memberId);

                if ($mClass::model()->hasAttribute('space_id')) {
                    if (isset($group->spaceId) && $group->spaceId != NULL) {
                        $condition.=' and space_id=:spaceId';
                        $params[':spaceId'] = $group->spaceId;
                    }
                }
                if ($mClass::model()->hasAttribute('app_id')) {
                    if (isset($group->appId) && $group->appId != NULL) {
                        $condition.=' and app_id=:appId';
                        $params[':appId'] = $group->appId;
                    }
                }
                $mObj = $mClass::model()->find($condition, $params);

                if ($mObj == NULL) {
                    $mGroupMember = new $mClass();
                    $mGroupMember->$memberCol = $memberId;
                    $mGroupMember->$groupCol = $group->getId();
                    if ($mClass::model()->hasAttribute('space_id')) {
                        if (isset($group->spaceId) && is_numeric($group->spaceId)) {
                            $mGroupMember->space_id = $group->spaceId;
                        }
                    }
                    if ($mClass::model()->hasAttribute('app_id')) {
                        if (isset($group->appId) && is_numeric($group->appId)) {
                            $mGroupMember->app_id = $group->appId;
                        }
                    }

                    return $mGroupMember->save();
                }
            }
        }

        return FALSE;
    }

    /**
     * 
     * @param BGroup $group
     * @param BEntity $member
     * @param type $context
     * @return boolean
     */
    public function removeGroupMembers($group, $member = null) {

        //$context = BRepository::getContext($context, $group);

        $memberId = NULL;
        $groupClass = get_class($group);
        //default memberClass
        $memberClass = preg_replace("/Group$/", "", $groupClass);
        if (is_string($member))
            $memberClass = $member;
        /*
          if ($member instanceof BEntity){
          $memberClass = get_class($member);
          $memberId = $member->getId();
          }
         * 
         */

        if (is_numeric($member)) {
            $memberId = $member;
            //$memberClass = preg_replace("/Group/", "", $groupClass);
        }

        if ($member instanceof BEntityWithGroup) {
            $memberId = $member->getId();
            $memberClass = get_class($member);
        }

        if (preg_match("/Group$/", $groupClass))
            $mClass = $groupClass . 'Member';
        else {
            $mClass = $groupClass . preg_replace("/^B/", "", $memberClass);
        }

        $statusId_deleted = BStatus::Status_Deleted_Id;

        //$statusId = $context->statusId;

        $condition = 'group_class = :GroupClass and member_class = :MemberClass and group_id = :GroupId
					and status != :StatusId';
        $params = array(':GroupClass' => $groupClass, ':MemberClass' => $memberClass, ':Status' => $statusId_deleted,
            ':GroupId' => $group->getId());

        if ($memberClass != NULL) {
            $condition .= ' and member_class = :MemberClass';
            $params[':MemberClass'] = $memberClass;
        }

        if ($memberId != NULL) {
            $condition .= ' and member_id = :MemberId';
            $params[':MemberId'] = $memberId;
        }

        if (isset($group->spaceId) && $group->spaceId != null) {
            $condition.='space_id=:spaceId';
            $params[':spaceId'] = $group->spaceId;
        }
        if (isset($group->appId) && $group->appId != NULL) {
            $condition.='app_id=:appId';
            $params[':appId'] = $group->appId;
        }

        $mObjs = $mClass::model()->findAll($condition, $params);

        if ($mObjs != NULL) {
            foreach ($mObjs as $mObj) {
                $mObj->status = $statusId_deleted;
                $mObj->save();
            }
            //return removed count
            return count($mObjs);
        }

        return FALSE;
    }

    public function removeGroupMembersByMemberId($groupClass, $memberId) {
        $group = new $groupClass();
        $mClass = $group->getMemberModelClass();

        $condition = 'member_id = :memberId';
        $params = array(':memberId' => $memberId);
        $mClass::model()->deleteAll($condition, $params);
    }

    /**
     * 
     * @param type $entity
     * @param type $context
     * @return \groupClass|boolean
     */
    public function findMemberGroups($entity, $group = NULL) {
        //$group = BRepository::getContext($group, $entity);
        //$class = get_class($this);
        //$mClass = preg_replace("/^B/", "BM", $class) . "Member";
        //$mClass = $group->groupMemberModelClass;
        //$memberClass = preg_replace('/Group/', '', $class);
        $memberClass = get_class($entity);
        //set default group class
        $groupClass = $entity->getGroupClass();

        /*
          if ($group instanceof BGroup)
          $groupClass = get_class($group);

          if (is_string($group))
          $groupClass = $group;

          if (preg_match("/Group$/", $groupClass))
          $mClass = $groupClass . 'Member';
          else {
          $mClass = $groupClass . preg_replace("/^B/", "BM", $memberClass);
          }
         * 
         */
        $mClass = $entity->getModelClassAsGroupMember($group);

        if ($group instanceof BGroup) {
            $groupClass = get_class($group);
        }

        $statusId = BStatus::find(BStatus::Status_Object_Deleted)->getId();

        $condition = 'status != :StatusId';
        $params = array(':StatusId' => $statusId);

        if ($entity instanceof BEntityWithGroup) {
            if (preg_match("/Group$/", $groupClass)) {
                $condition.=' and member_id=:memberId';
                $params[':memberId'] = $entity->getId();

                if ($mClass::model()->hasAttribute('member_class')) {
                    $condition.=' and member_class=:MemberClass';
                    $params[':MemberClass'] = get_class($entity);
                }
            } else {
                $memberCol = strtolower(preg_replace("/^B/", "", get_class($entity))) . "_id";
                $condition.=' and ' . $memberCol . ' =:memberId';
                $params[':memberId'] = $entity->getId();
            }
        }

        if ($group instanceof BGroup) {
            if (isset($group->spaceId) && $group->spaceId > 0) {
                $condition.=' and space_id=:spaceId';
                $params[':spaceId'] = $group->spaceId;
            }
            if (isset($group->appId) && $group->appId > 0) {
                $condition.=' and app_id=:appId';
                $params[':appId'] = $group->appId;
            }
        }

        $mObjs = $mClass::model()->findAll($condition, $params);

        if ($entity instanceof BEntityWithGroup) {
            $groups = array();
            foreach ($mObjs as $mObj) {
                if (preg_match("/Group$/", $groupClass)) {
                    $groups[$mObj->group_id] = new $groupClass($mObj->group_id);
                } else {
                    $groupCol = strtolower(preg_replace("/^B/", "", $groupClass)) . "_id";
                    $groups[$mObj->$groupCol] = new $groupClass($mObj->$groupCol);
                }
            }

            if ($groups != NULL)
                return $groups;
        }

        return FALSE;
    }

    /**
     * 
     * @param BGroup $entity
     * @param type $context
     * @return \memberClass|boolean
     */
    public function findGroupMember($entity, $member = NULL) {

        $groupClass = get_class($entity);

        //default member class
        $memberClass = $groupClass . 'Member';

        if ($member instanceof BEntityWithGroup)
            $memberClass = get_class($member);

        if (is_string($member))
            $memberClass = $member;

        if (preg_match("/Group$/", $groupClass))
            $mClass = $entity->getModelClass() . 'Member';
        else {
            $mClass = $entity->getModelClass() . preg_replace("/^B/", "", $memberClass);
        }

        $statusId = BStatus::Status_Deleted_Id;

        $condition = 'status != :StatusId';
        $params = array(':StatusId' => $statusId);

        if ($entity instanceof BGroup) {
            $groupClass = $groupClass == NULL ? get_class($entity) : $groupClass;
            if (preg_match("/Group/", $groupClass)) {
                $condition.=' and group_id=:groupId';
                $params[':groupId'] = $entity->getId();
                $condition.=' and group_class=:groupClass';
                $params[':groupClass'] = get_class($entity);
            } else {
                $groupCol = strtolower(preg_replace("/^B/", "", get_class($entity))) . "_id";
                $condition.=' and ' . $groupCol . ' =:groupId';
                $params[':groupId'] = $entity->getId();
            }
        }

        if (isset($member->spaceId) && $member->spaceId > 0) {
            $condition.=' and space_id=:spaceId';
            $params[':spaceId'] = $member->spaceId;
        }
        if (isset($member->appId) && $member->appId > 0) {
            $condition.=' and app_id=:appId';
            $params[':appId'] = $member->appId;
        }

        $mObjs = $mClass::model()->findAll($condition, $params);

        if ($entity instanceof BGroup) {
            $members = array();
            foreach ($mObjs as $mObj) {
                if (preg_match("/Group$/", $groupClass)) {
                    $members[$mObj->member_id] = new $memberClass($mObj->member_id);
                } else {
                    $memberCol = strtolower(preg_replace("/^B/", "", $memberClass)) . "_id";
                    $members[$mObj->$memberCol] = new $memberClass($mObj->$memberCol);
                }
            }

            if ($members != NULL)
                return $members;
        }

        return FALSE;
    }

    static function isSingleTreeItem($entity) {
        return property_exists($entity, 'parentId');
    }

}

?>
